home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / tiff / tiff.c < prev    next >
C/C++ Source or Header  |  1988-11-02  |  24KB  |  904 lines

  1. /* tiff.c - routines that parse tiff files
  2.  *
  3.  * Created 88-10-31, out of rev 3.8.
  4.  */
  5.  
  6. #include "aldtypes.h"
  7. #include "aldmem.h"
  8. #include "aldutils.h"
  9. #include "imtypes.h"
  10. #include "swap.h"
  11. #include "immem.h"
  12. #include "vio.h"
  13. #include "imag.h"
  14. #include "imtiff.h"
  15. #include "tiff.h"
  16. #include "ImErr.h"
  17. #include "ImErr2.h"        /* application-dependent! for WarningAlert proto and IA_PLACE_IMAGE */
  18. #include "tiffrout.h"
  19.  
  20. extern char *ErrorMessages;
  21.  
  22. #define min(x,y) (((y)<(x)) ? (y) : (x))
  23. #define    MAXBYTE    255
  24.  
  25.  
  26. /************************ mostly local procedures *************************/
  27.  
  28.  
  29. /* get data -- handles file/table and byte-order problems
  30.  * 64K max
  31.  */
  32. RC GtData (pDloc, order, pos, n, dtype, lpData)
  33. PDLOC    pDloc;        /* data location - open file or locked-down table */
  34. WORD    order;        /* byte order -- INTELTIFF or MOTOROLATIFF */
  35. DWORD    pos;        /* file/table position, with respect to its beginning */
  36. WORD    n;            /* number of data elements to read */
  37. WORD    dtype;        /* data type: TIFFSHORT, etc */
  38. LPSTR    lpData;        /* where to put the data */
  39. {
  40.         RC        err;
  41.         WORD    tsize;
  42.         WORD    BytesToRead;
  43.         
  44.         if (n == 0)
  45.             goto done;
  46.  
  47.         /* read the data
  48.          */
  49.         if (err = GtTiffSizeof (dtype, &tsize)) {
  50.             DBMSG(("GtData: bad dtype\n"));
  51.             return err;
  52.         }
  53.         BytesToRead = tsize * n;
  54.         if (err = VRead (pDloc, pos, BytesToRead, lpData)) {
  55.             DBMSG(("GtData: VRead\n"));
  56.             DBMSG((" err=%u pos=%lu BytesToRead=%u\n",
  57.              err,pos,BytesToRead));
  58.             return err;
  59.         }
  60.  
  61.         /* change the byte order, if necessary
  62.          */
  63.         if (order != MOTOROLATIFF && order != INTELTIFF) {
  64.             DBMSG(("GtData: bad byte order: %u\n", order));
  65.             return IM_BUG;    /* should have been caught earlier */
  66.         }
  67. #ifdef WINDOWS
  68.         if (order == MOTOROLATIFF) {
  69. #endif
  70. #ifdef MACINTOSH
  71.         if (order == INTELTIFF) {
  72. #endif
  73.             if (dtype == TIFFSHORT)
  74.                 swab (lpData, lpData, BytesToRead);
  75.             else if (dtype == TIFFLONG)
  76.                 swaw (lpData, lpData, BytesToRead);
  77.             else if (dtype == TIFFRATIONAL)
  78.                 swaw (lpData, lpData, BytesToRead);
  79.             else if (dtype == TIFFSIGNED)
  80.                 swab (lpData, lpData, BytesToRead);
  81.         }
  82.  
  83.         /* return
  84.          */
  85. done:    return SUCCESS;
  86. }
  87.  
  88. #define CHUNKSIZE 32768L
  89.  
  90. /* get a possibly >64K chunk of data, by calling GtData repeatedly
  91.  */
  92. RC GtHugeData (pDloc, order, pos, dwN, dtype, lpData)
  93. PDLOC    pDloc;        /* data location - open file or locked-down table */
  94. WORD    order;        /* INTELTIFF or MOTOROLATIFF */
  95. DWORD    pos;        /* file/table position, with respect to its beginning */
  96. DWORD    dwN;        /* number of data elements to read */
  97. WORD    dtype;        /* data type: TIFFSHORT, etc */
  98. LPSTR    lpData;        /* where to put the data */
  99. {
  100.         RC        err = SUCCESS;
  101.         WORD    tsize;
  102.         DWORD    ElementsLeft;
  103.         DWORD    ElementsToRead;
  104.         LPSTR    lpOut = lpData;
  105.         DWORD    ElementsPerChunk;
  106.         
  107.         /* DBMSG(("GtHugeData: top\n")); */
  108.  
  109.         /* get size of elements
  110.          */
  111.         if (err = GtTiffSizeof (dtype, &tsize)) {
  112.             DBMSG(("GtHugeData: bad dtype\n"));
  113.             return err;
  114.         }
  115.  
  116.         /* calculate number of elements per chunk
  117.          */
  118.         ElementsPerChunk = CHUNKSIZE / tsize;
  119.         /* DBMSG((" ElementsPerChunk=%lu\n",ElementsPerChunk)); */
  120.  
  121.         /* read repeatedly
  122.          */
  123.         ElementsLeft = dwN;
  124.         while (ElementsLeft > 0L) {
  125.             ElementsToRead = min (ElementsPerChunk, ElementsLeft);
  126.             /* DBMSG((" ElementsToRead=%lu\n",ElementsToRead)); */
  127.             if (err = GtData (pDloc, order, pos, (WORD)ElementsToRead,
  128.              dtype, lpOut)) {
  129.                 DBMSG(("GtHugeData: GtData\n"));
  130.                 goto cu;
  131.             }
  132.             lpOut += ElementsToRead * tsize;
  133.             ElementsLeft -= ElementsToRead;
  134.             /* DBMSG((" ElementsLeft=%lu\n",ElementsLeft)); */
  135.         }
  136.         /* DBMSG(("GtHugeData: bottom\n")); */
  137. cu:        return err;
  138. }
  139.  
  140. /* get TIFF 8-byte header
  141.  * currently only probably portable.  depends somewhat on compiler's 
  142.  * structure organization.
  143.  */
  144. RC GtTiffHdr (pDloc, pHdr)
  145. PDLOC    pDloc;
  146. register TIFFHDR *pHdr;
  147. {
  148.         RC err;
  149.  
  150.         /* get the first word -- the byte order.
  151.          * first, set dlOrder to either valid value, since we will immediately
  152.          * change it.  sort of a chicken and egg situation.
  153.          */
  154.         /* pDloc->dlOrder = INTELTIFF; */
  155.         if (err = GtData (pDloc, INTELTIFF, (DWORD) 0, 1, TIFFSHORT, 
  156.          (LPSTR)&pHdr->thByteOrder)) {
  157.             DBMSG(("GtTiffHdr: A\n"));
  158.             return err;
  159.         }
  160.         /* *pOrder = pHdr->thByteOrder; */
  161.  
  162.         /* get the version
  163.          */
  164.         if (err = GtData (pDloc, pHdr->thByteOrder, (DWORD) 2, 1, TIFFSHORT, 
  165.          (LPSTR)&pHdr->thVersion)) {
  166.             DBMSG(("GtTiffHdr: AA\n"));
  167.             return err;
  168.         }
  169.  
  170.         /* get the double word (IFD offset)
  171.          */
  172.         if (err = GtData (pDloc, pHdr->thByteOrder, (DWORD)4, 1, TIFFLONG, 
  173.          (LPSTR)&pHdr->thIfdOffset)) {
  174.             DBMSG(("GtTiffHdr: B\n"));
  175.             return err;
  176.         }
  177. #if 0
  178.         DBMSG(("GtTiffHdr: ByteOrder=%x Version=%u IfdOffset=%lu\n",
  179.          pHdr->thByteOrder, pHdr->thVersion, pHdr->thIfdOffset));
  180. #endif /* 0 */
  181.  
  182.         /* return
  183.          */
  184.         return SUCCESS;
  185. }
  186.  
  187. /* get TIFF directory entry
  188.  */
  189. RC GtTiffEntry (pDloc, order, EntryOffset, pDe)
  190. PDLOC    pDloc;
  191. WORD    order;
  192. DWORD    EntryOffset;
  193. register DIRENTRY    *pDe;
  194. {
  195.         RC err;
  196.         DWORD BytesToRead;
  197.         WORD tsize;
  198.         WORD wTmp;
  199.  
  200.         /* get the 2 words beginning with deTag
  201.          */
  202.         if (err = GtData (pDloc, order, EntryOffset, 2, TIFFSHORT,
  203.          (LPSTR)&pDe->deTag)) {
  204.             DBMSG(("GtTiffEntry: A\n"));
  205.             return err;
  206.         }
  207.  
  208.         /* get the 2 dwords, beginning with deLength
  209.          */
  210.         if (err = GtData (pDloc, order, EntryOffset + 4L, 2, TIFFLONG,
  211.          (LPSTR)&pDe->deLength)) {
  212.             DBMSG(("GtTiffEntry: B\n"));
  213.             return err;
  214.         }
  215.  
  216.         /* fix up deVal, if it's not really a LONG
  217.          */
  218. #ifdef WINDOWS
  219.         if (order == MOTOROLATIFF) {
  220. #endif
  221. #ifdef MACINTOSH
  222.         if (order == INTELTIFF) {
  223. #endif
  224.             if (err = GtTiffSizeof (pDe->deType, &tsize)) {
  225.                 DBMSG(("GtTiffEntry: GtTiffSizeof\n"));
  226.                 WARN ((HWND)NULL, IM_WARNING, IM_BAD_TTYPE);
  227.                 return err;
  228.             }
  229.             BytesToRead = (DWORD)tsize * pDe->deLength;
  230.             if (BytesToRead <= 4) {
  231.                 if (tsize == 2) {    /* swap words */
  232.                     wTmp = * (WORD *) &pDe->deVal;
  233.                     * (WORD *) &pDe->deVal = * ((WORD *) &pDe->deVal + 1);
  234.                     * ((WORD *) &pDe->deVal + 1) = wTmp;
  235.                 }
  236.                 else if (tsize == 1) {    /* swap bytes */
  237.                     swaw ((LPSTR)&pDe->deVal, (LPSTR)&pDe->deVal, 4);
  238.                 }
  239.             }
  240.         }
  241.  
  242.         /* return
  243.          */
  244.         return SUCCESS;
  245. }
  246.  
  247.  
  248. /* Fill a Tiff Field structure
  249.  * Note: the caller should probably not totally die upon getting an error.
  250.  * Private data types are possible, for one thing.  Just don't set the
  251.  * existence flag for the field.
  252.  */
  253. RC FillTField ARGS((PDLOC,WORD,DIRENTRY *,DWORD,TFIELD *));
  254. LOCAL RC FillTField (pDloc, order, pDe, EntryOffset, pTF)
  255. PDLOC                pDloc;
  256. WORD                order;
  257. register DIRENTRY    *pDe;
  258. DWORD                EntryOffset;
  259. register TFIELD        *pTF;
  260. {
  261.         RC        err = SUCCESS;
  262.         HANDLE    h;
  263.         LPSTR    lp;
  264.         WORD    TypeSize;
  265.         DWORD    BytesToRead;
  266.  
  267.         /* copy tag, type, and length from DIRENTRY structure
  268.          */
  269.         pTF->Texists = TRUE;
  270.         pTF->Ttag = pDe->deTag;
  271.         pTF->Ttype = pDe->deType;
  272.         pTF->Tlength = pDe->deLength;
  273.         
  274.         /* record the offset, for possible later modify-in-place action
  275.          */
  276.         pTF->Tentryoffset = EntryOffset;
  277.  
  278.         /* calculate needed space
  279.          */
  280.         if (err = GtTiffSizeof (pTF->Ttype, &TypeSize)) {
  281.             DBMSG(("FillTField: unknown type\n"));
  282.             goto cu0;
  283.         }
  284.         BytesToRead = (DWORD)TypeSize * pTF->Tlength;
  285.  
  286.         /* if <= 4 bytes, we're almost done.  else we have to do some
  287.          * work.
  288.          */
  289.         pTF->Talloc = FALSE;    /* just to be safe */
  290.         if (BytesToRead <= 4) {
  291.             pTF->val.Tdword = pDe->deVal;
  292.         }
  293.         else {
  294.  
  295.             /* allocate and lock a buffer
  296.              */
  297.             if (!(h = MMAlloc (BytesToRead))) {
  298.                 DBMSG(("FillTField: h\n"));
  299.                 err = IM_MEM_FULL;
  300.                 goto cu0;
  301.             }
  302.             if (!(lp = MMLock (h))) {
  303.                 DBMSG(("FillTField: lp\n"));
  304.                 err = IM_MEM_FAIL;
  305.                 MMFree (h);
  306.                 goto cu0;
  307.             }
  308.  
  309.             /* read the data
  310.              */
  311.             if (err = GtHugeData (pDloc, order, pDe->deVal, pDe->deLength,
  312.              pDe->deType, lp)) {
  313.                 DBMSG(("FillTField: GtHugeData\n"));
  314.                 MMUnlock (h);
  315.                 MMFree (h);
  316.                 goto cu0;
  317.             }
  318.             
  319.             /* make sure that the val union contains the first N values from
  320.              * the memory buffer, so that we can use things like p->iBitsPerSample
  321.              * constructs even if there are 3 BitsPerSample values.
  322.              */
  323.             lmemcpy ((LPSTR) &pTF->val.Tchar[0], lp, 4);
  324.  
  325.             /* unlock the buffer
  326.              */
  327.             MMUnlock (h);
  328.  
  329.             /* stuff the handle into the TFIELD structure
  330.              */
  331.             pTF->Thandle = h;
  332.             pTF->Talloc = TRUE;
  333.  
  334.         } /* end of greater-than-4-byte case */
  335.  
  336.         /* return
  337.          */
  338. cu0:    return err;
  339. }
  340.  
  341.  
  342. RC TypeConvert ARGS((TFIELD *, WORD));
  343. LOCAL RC TypeConvert (pTF, totype)
  344. register TFIELD    *pTF;
  345. WORD    totype;        /* TIFFBYTE, etc */
  346. {
  347.         RC        err = SUCCESS;
  348.         
  349.         WORD    fromtype;
  350.         DWORD    dwLength;
  351.         
  352.         WORD    SrcSize;
  353.         DWORD    SrcBytes;
  354.         DWORD    SrcVal;
  355.         LPSTR    lpSrc;
  356.         
  357.         WORD    DstSize;
  358.         DWORD    DstBytes;
  359.         DWORD    DstVal;
  360.         LPSTR    lpDst;
  361.         HANDLE    hDst = (HANDLE)NULL;
  362.         
  363.         /* DBMSG(("TypeConvert: top\n")); */
  364.         
  365.         /* shorthands:
  366.          */
  367.         fromtype = pTF->Ttype;
  368.         dwLength = pTF->Tlength;
  369.         
  370.         /* DBMSG(("tfield:\n"));
  371.          * DBMSG((" Talloc=%u Ttag=%u Ttype=%u Tlength=%lu val=%lx\n",
  372.          *  pTF->Talloc,pTF->Ttag,pTF->Ttype,pTF->Tlength,pTF->val.Tdword));
  373.          */
  374.  
  375.         /* if the same type, do nothing
  376.          */
  377.         if (totype == fromtype) {
  378.             goto done;
  379.         }
  380.         
  381.         /* calculate number of source bytes 
  382.          */
  383.         if (err = GtTiffSizeof (fromtype, &SrcSize)) {
  384.             DBMSG(("TypeConvert: bad dtype src\n"));
  385.             goto done;
  386.         }
  387.         SrcBytes = (DWORD)SrcSize * dwLength;
  388.         
  389.         /* point to source data
  390.          */
  391.         if (SrcBytes <= (DWORD)4) {
  392.             if (pTF->Talloc) {
  393.                 DBMSG(("TypeConvert: size error A\n"));
  394.                 err = IM_BUG;    /* programming error */
  395.                 goto done;
  396.             }
  397.             SrcVal = pTF->val.Tdword;
  398.             lpSrc = (LPSTR)&SrcVal;
  399.         } else {
  400.             if (!pTF->Talloc) {
  401.                 DBMSG(("TypeConvert: size error B\n"));
  402.                 err = IM_BUG;    /* programming error */
  403.                 goto done;
  404.             }
  405.             if (pTF->Thandle == (HANDLE)NULL) {
  406.                 DBMSG(("TypeConvert: null handle\n"));
  407.                 err = IM_BUG;    /* programming error */
  408.                 goto done;
  409.             }
  410.             if ((lpSrc = MMLock (pTF->Thandle)) == (LPSTR)NULL) {
  411.                 DBMSG(("TypeConvert: Thandle\n"));
  412.                 err = IM_MEM_FAIL;
  413.                 goto done;
  414.             }
  415.         }
  416.         
  417.         /* calculate number of destination bytes
  418.          *
  419.          * In the case of ASCII source and integer or
  420.          * floating point destination, we are going to
  421.          * allocate too much space, and quite possibly
  422.          * allocate when the result would fit into 4
  423.          * bytes, so make sure we take that into consideration
  424.          * below.
  425.          */
  426.         if (err = GtTiffSizeof (totype, &DstSize)) {
  427.             DBMSG(("TypeConvert: bad dtype dst\n"));
  428.             if (pTF->Talloc) MMUnlock (pTF->Thandle);            
  429.             goto done;
  430.         }
  431.         DstBytes = (DWORD)DstSize * dwLength;
  432.         
  433.         /* point to destination data
  434.          */
  435.         if (DstBytes <= (DWORD)4)
  436.             lpDst = (LPSTR)&DstVal;
  437.         else {
  438.             if (err = GetItLockIt (DstBytes, &hDst,
  439.              (LPBYTE *)&lpDst)) {
  440.                 DBMSG(("TypeConvert: hDst\n"));
  441.                 if (pTF->Talloc) MMUnlock (pTF->Thandle);
  442.                 goto done;
  443.             }
  444.         }
  445.                 
  446.         /* convert depending on source and destination type
  447.          */
  448.         {
  449.             /* if TIFFRATIONAL, convert to floating point or
  450.              * integer. Note that I am relaxing the definition
  451.              * of RATIONAL to include negative numbers.
  452.              */
  453.             if (fromtype == TIFFRATIONAL && 
  454.              (totype == TIFFFLOAT || totype == TIFFSIGNED ||
  455.              totype == TIFFSHORT)) {
  456.                  register long FAR    *lpSrcPtr;    /* assumption: long & DWORD are same length */
  457.                  register LPSTR        lpDstPtr;
  458.                 register DWORD        dwCnt;
  459.                 float                FloatVal;
  460.                 short                ShortVal;
  461.                 
  462.                 /* set up
  463.                  */
  464.                 lpSrcPtr = (long FAR *)lpSrc;
  465.                 lpDstPtr = lpDst;
  466.                 
  467.                 /* for each rational...
  468.                  */
  469.                 for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
  470.                 
  471.                     /* calculate a float equivalent
  472.                      */
  473.                     if (*(lpSrcPtr +1) == (DWORD)0) {
  474.                         FloatVal = (float)0.0;
  475.                     } else {
  476.                         FloatVal = (float)*lpSrcPtr / (float)*(lpSrcPtr+1);
  477.                     }
  478.                     
  479.                     /* translate if necessary, and store
  480.                      * into the destination array
  481.                      */
  482.                     if (totype == TIFFFLOAT) {
  483.                         *((float FAR *)lpDstPtr) = FloatVal;
  484.                     } else {
  485.                         if (FloatVal >= (float)0.0) {
  486.                             ShortVal = (short)(FloatVal + .5);
  487.                         } else {
  488.                             /* is this right? */
  489.                             ShortVal = (short)(FloatVal - .5);
  490.                         }
  491.                     }
  492.                     if (totype == TIFFSHORT) {
  493.                         *((LPWORD)lpDstPtr) = (WORD)ShortVal;
  494.                     } else if (totype == TIFFSIGNED) {
  495.                         *((short FAR *)lpDstPtr) = ShortVal;
  496.                     }
  497.                     
  498.                     /* increment the pointers
  499.                      */
  500.                     lpSrcPtr++;
  501.                     lpDstPtr += DstSize;
  502.                 }
  503.                 
  504.                 /* make sure that the val section contains the first N values from
  505.                  * the destination array
  506.                  */
  507.                 if (DstBytes > (DWORD)4) {
  508.                     lmemcpy ((LPSTR) &pTF->val.Tdword, (LPSTR)lpDst, 4);
  509.                 }
  510.                 
  511.                 /* set the new type
  512.                  */
  513.                 pTF->Ttype = totype;
  514.             
  515.             } /* end of rational to float/short/WORD section */
  516.             
  517.             /* else if an unsigned integer (TIFFBYTE, TIFFSHORT, or TIFFLONG),
  518.              * do the appropriate conversion.  I probably should check for
  519.              * problems when converting to something smaller.  TODO.
  520.              */
  521.             else if ((fromtype == TIFFBYTE || fromtype == TIFFSHORT ||
  522.              fromtype == TIFFLONG) &&
  523.              (totype == TIFFBYTE || totype == TIFFSHORT ||
  524.              totype == TIFFLONG)) {
  525.                  register LPSTR        lpSrcPtr = lpSrc;
  526.                  register LPSTR        lpDstPtr = lpDst;
  527.                 register DWORD        dwCnt;
  528.                 register WORD        TiffShort;
  529.                 register DWORD        TiffLong;
  530.                 
  531.                 if (fromtype == TIFFBYTE && totype == TIFFSHORT) {
  532.                     for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
  533.                         *((LPWORD)lpDstPtr) = (WORD)*((LPBYTE)lpSrcPtr);
  534.                         lpSrcPtr += SrcSize;
  535.                         lpDstPtr += DstSize;
  536.                     }
  537.                 } else if (fromtype == TIFFBYTE && totype == TIFFLONG) {
  538.                     for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
  539.                         *((LPDWORD)lpDstPtr) = (DWORD)*((LPBYTE)lpSrcPtr);
  540.                         lpSrcPtr += SrcSize;
  541.                         lpDstPtr += DstSize;
  542.                     }
  543.                 } else if (fromtype == TIFFSHORT && totype == TIFFBYTE) {
  544.                     for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
  545.                         TiffShort = *((LPWORD)lpSrcPtr);
  546.                         if (TiffShort > MAXBYTE) {
  547.                             TiffShort = MAXBYTE;
  548.                         }
  549.                         *((LPBYTE)lpDstPtr) = (BYTE)TiffShort;
  550.                         lpSrcPtr += SrcSize;
  551.                         lpDstPtr += DstSize;
  552.                     }
  553.                 } else if (fromtype == TIFFSHORT && totype == TIFFLONG) {
  554.                     for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
  555.                         *((LPDWORD)lpDstPtr) = (DWORD)*((LPWORD)lpSrcPtr);
  556.                         lpSrcPtr += SrcSize;
  557.                         lpDstPtr += DstSize;
  558.                     }
  559.                 } else if (fromtype == TIFFLONG && totype == TIFFBYTE) {
  560.                     for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
  561.                         TiffLong = *((LPDWORD)lpSrcPtr);
  562.                         if (TiffLong > MAXWORD) {
  563.                             TiffLong = MAXWORD;
  564.                         }
  565.                         *((LPBYTE)lpDstPtr) = (BYTE)TiffLong;
  566.                         lpSrcPtr += SrcSize;
  567.                         lpDstPtr += DstSize;
  568.                     }
  569.                 } else if (fromtype == TIFFLONG && totype == TIFFSHORT) {
  570.                     for (dwCnt = (DWORD)0; dwCnt < dwLength; dwCnt++) {
  571.                         TiffLong = *((LPDWORD)lpSrcPtr);
  572.                         if (TiffLong > MAXWORD) {
  573.                             TiffLong = MAXWORD;
  574.                         }
  575.                         *((LPWORD)lpDstPtr) = (WORD)TiffLong;
  576.                         lpSrcPtr += SrcSize;
  577.                         lpDstPtr += DstSize;
  578.                     }
  579.                 }
  580.                 
  581.                 /* make sure that the val section contains the first N values from
  582.                  * the destination array, so that I can have a 3-valued BitsPerSample
  583.                  * (forced to be the same) but still get "the" BitsPerSample value
  584.                  * by using the p->iBitsPerSample contruct
  585.                  */
  586.                 if (DstBytes > (DWORD)4) {
  587.                     lmemcpy ((LPSTR) &pTF->val.Tdword, (LPSTR)lpDst, 4);
  588.                 }
  589.                 
  590.                 /* set the new type
  591.                  */
  592.                 pTF->Ttype = totype;
  593.             } /* end of unsigned section */
  594.             
  595.             /* else if none of the above cases, give up.
  596.              */
  597.             else {
  598.                 DBMSG(("TypeConvert: type problem. fromtype=%d totype=%d\n",
  599.                  fromtype, totype));
  600.                 if (pTF->Talloc) MMUnlock (pTF->Thandle);
  601.                 if (hDst) {
  602.                     UnlockItFreeIt (hDst);
  603.                     hDst = (HANDLE) NULL;
  604.                 }
  605.                 err = IM_BUG;    /* programming error */
  606.                 goto done;
  607.             }
  608.  
  609.         } /* end of conversion section */
  610.         
  611.         /* if neither the source nor destination is allocated,
  612.          * just copy into the 4-byte value
  613.          */
  614.         if (!pTF->Talloc && !hDst) {
  615.             pTF->val.Tdword = DstVal;
  616.         }
  617.         
  618.         /* else if source and destination are both allocated,
  619.          * free the old buffer, and store the new destination handle
  620.          */
  621.         else if (pTF->Talloc && hDst) {
  622.             UnlockItFreeIt (pTF->Thandle);
  623.             pTF->Thandle = hDst;
  624.             MMUnlock (hDst);
  625.         }
  626.         
  627.         /* else if destination is allocated, but not the source,
  628.          * just store the new destination handle
  629.          */
  630.         else if (!pTF->Talloc && hDst) {
  631.             pTF->Thandle = hDst;
  632.             MMUnlock (pTF->Thandle);
  633.             pTF->Talloc = TRUE;
  634.         }
  635.         
  636.         /* else if source is allocated, but not the destination,
  637.          * unlock and free the buffer, and copy the value.
  638.          */
  639.         else if (pTF->Talloc && !hDst) {
  640.             UnlockItFreeIt (pTF->Thandle);
  641.             pTF->Talloc = FALSE;
  642.             pTF->val.Tdword = DstVal;
  643.         }
  644.         
  645.         /* return
  646.          */
  647. done:    return err;
  648. }
  649.  
  650.  
  651. /* check for bad values, convert from one format to another
  652.  * if necessary, and store the information in the appropriate
  653.  * TFIELD structure in the IMAG structure
  654.  */
  655. RC NicefyTField ARGS((TFIELD *, IMAG *));
  656. RC NicefyTField (pTF, x)
  657. register TFIELD    *pTF;
  658. register IMAG    *x;
  659. {
  660.         RC        err = SUCCESS;
  661.         register WORD    Tag;
  662.  
  663.         Tag = pTF->Ttag;
  664.         /* DBMSG(("Nicefy: unsigned tag=%u   signed tag=%d\n",
  665.          *  pTF->Ttag, pTF->Ttag));
  666.          */
  667.  
  668.         if (Tag == TGNEWSUBFILETYPE) {
  669.             if (err = TypeConvert (pTF, TIFFLONG))
  670.                 goto cu0;
  671.             pTF->Texists = TRUE;
  672.             x->tf[X_NEWSUBFILETYPE] = *pTF;    /* structure copy */
  673.             
  674.         } else if (Tag == TGIMAGEWIDTH) {
  675.             if (err = TypeConvert (pTF, TIFFSHORT))
  676.                 goto cu0;
  677.             pTF->Texists = TRUE;
  678.             x->tf[X_IMAGEWIDTH] = *pTF;    /* structure copy */
  679.  
  680.         } else if (Tag == TGIMAGELENGTH) {
  681.             if (err = TypeConvert (pTF, TIFFSHORT))
  682.                 goto cu0;
  683.             pTF->Texists = TRUE;
  684.             x->tf[X_IMAGELENGTH] = *pTF;    /* structure copy */
  685.  
  686.         } else if (Tag == TGBITSPERSAMPLE) {
  687.             if (err = TypeConvert (pTF, TIFFSHORT))
  688.                 goto cu0;
  689.             pTF->Texists = TRUE;
  690.             x->tf[X_BITSPERSAMPLE] = *pTF;    /* structure copy */
  691.  
  692.         } else if (Tag == TGCOMPRESSION) {
  693.             if (err = TypeConvert (pTF, TIFFSHORT))
  694.                 goto cu0;
  695.             pTF->Texists = TRUE;
  696.             x->tf[X_COMPRESSION] = *pTF;    /* structure copy */
  697.  
  698.         } else if (Tag == TGPHOTOMETRICINTERPRETATION) {
  699.             if (err = TypeConvert (pTF, TIFFSHORT))
  700.                 goto cu0;
  701.             pTF->Texists = TRUE;
  702.             x->tf[X_PHOTOMETRICINTERP] = *pTF;    /* structure copy */
  703.  
  704.         } else if (Tag == TGSTRIPOFFSETS) {
  705.             if (err = TypeConvert (pTF, TIFFLONG))
  706.                 goto cu0;
  707.             pTF->Texists = TRUE;
  708.             x->tf[X_STRIPOFFSETS] = *pTF;    /* structure copy */
  709.         
  710.         } else if (Tag == TGSAMPLESPERPIXEL) {
  711.             if (err = TypeConvert (pTF, TIFFSHORT))
  712.                 goto cu0;
  713.             pTF->Texists = TRUE;
  714.             x->tf[X_SAMPLES] = *pTF;        /* structure copy */
  715.             
  716.         } else if (Tag == TGSTRIPBYTECOUNTS) {
  717.             if (err = TypeConvert (pTF, TIFFLONG))
  718.                 goto cu0;
  719.             pTF->Texists = TRUE;
  720.             x->tf[X_STRIPBYTECOUNTS] = *pTF;    /* structure copy */
  721.  
  722.         } else if (Tag == TGROWSPERSTRIP) {
  723.             if (err = TypeConvert (pTF, TIFFSHORT))
  724.                 goto cu0;
  725.             pTF->Texists = TRUE;
  726.             x->tf[X_ROWSPERSTRIP] = *pTF;    /* structure copy */
  727.         
  728.         } else if (Tag == TGXRESOLUTION) {
  729.             if (err = TypeConvert (pTF, TIFFFLOAT))
  730.                 goto cu0;
  731.             pTF->Texists = TRUE;
  732.             x->tf[X_XRESOLUTION] = *pTF;    /* structure copy */
  733.             if (x->fXResolution == (float)0.0)
  734.                 x->fXResolution = (float)300.0;
  735.  
  736.         } else if (Tag == TGYRESOLUTION) {
  737.             if (err = TypeConvert (pTF, TIFFFLOAT))
  738.                 goto cu0;
  739.             pTF->Texists = TRUE;
  740.             x->tf[X_YRESOLUTION] = *pTF;    /* structure copy */
  741.             if (x->fYResolution == (float)0.0)
  742.                 x->fYResolution = (float)300.0;
  743.  
  744.         } else if (Tag == TGPLANARCONFIGURATION) {
  745.             if (err = TypeConvert (pTF, TIFFSHORT))
  746.                 goto cu0;
  747. #if 0
  748.             pTF->Texists = TRUE;
  749.             x->tf[X_PLANAR] = *pTF;        /* structure copy */
  750. #endif
  751.         
  752.         } else if (Tag == TGGRAYUNIT) {
  753.             if (err = TypeConvert (pTF, TIFFSHORT))
  754.                 goto cu0;
  755.             pTF->Texists = TRUE;
  756.             x->tf[X_GRAYUNIT] = *pTF;    /* structure copy */
  757.             
  758.         } else if (Tag == TGGRAYCURVE) {
  759.             if (err = TypeConvert (pTF, TIFFSHORT))
  760.                 goto cu0;
  761.             pTF->Texists = TRUE;
  762.             x->tf[X_GRAYCURVE] = *pTF;    /* structure copy */
  763.         
  764.         } else if (Tag == TGRESOLUTIONUNIT) {
  765.             if (err = TypeConvert (pTF, TIFFSHORT))
  766.                 goto cu0;
  767.             pTF->Texists = TRUE;
  768.             x->tf[X_RESOLUTIONUNIT] = *pTF;    /* structure copy */
  769.         
  770.         } else if (Tag == TGPREDICTOR) {
  771.             if (err = TypeConvert (pTF, TIFFSHORT))
  772.                 goto cu0;
  773.             pTF->Texists = TRUE;
  774.             x->tf[X_PREDICTOR] = *pTF;    /* structure copy */
  775.  
  776.         } else {
  777.             /* DBMSG(("GtTiffInfo: unrecognized tag %d\n",de.deTag)); */
  778.             /* 
  779.              * no big deal, probably.
  780.              */
  781.         }
  782.  
  783. cu0:    return err;
  784. }
  785.  
  786.  
  787. /************************ exported procedures **********************/
  788.  
  789. /* read all the TIFF fields that we care about.
  790.  * if from file, it should be open for read.
  791.  * currently, subsequent IFD's are ignored.
  792.  *
  793.  * make sure you fill out the DLOC structure before calling this routine.
  794.  */
  795. RC GtTiffInfo (pDloc, x)
  796. PDLOC            pDloc;    /* table/file input structure */
  797. register IMAG    *x;        /* this is where the field information will be put */
  798. {
  799.         RC err = SUCCESS;
  800.         TIFFHDR th;
  801.         DIRENTRY de;
  802.         TFIELD    tf;
  803.         WORD IfdEntries;
  804.         DWORD NextIfd;
  805.         DWORD EntryOffset;
  806.         WORD ii;
  807.         DWORD location;
  808.  
  809.         /* DBMSG(("GtTiffInfo: top\n")); */
  810.  
  811.         /* initialize the structure
  812.          */
  813.         InitImag (x);
  814.         
  815.         /* get the 8-byte header
  816.          */
  817.         if (err = GtTiffHdr (pDloc, &th)) {
  818.             DBMSG(("GtTiffInfo(): can't read header.\n"));
  819.             goto cu0;
  820.         }
  821.         x->iFileType = th.thByteOrder;
  822.         /* pDloc->dlOrder = th.thByteOrder; */
  823.         
  824.         /* check version
  825.          */
  826.         if (th.thVersion != VERSION42) {
  827.             DBMSG(("GtTiffInfo: wrong version\n"));
  828.             err = IM_BUG;    /* should have been caught earlier */
  829.             goto cu0;
  830.         }
  831.         x->iVersion = th.thVersion;
  832.         
  833.         /* read the number of directory entries
  834.          */
  835.         if (err = GtData (pDloc, th.thByteOrder, th.thIfdOffset, 1, TIFFSHORT,
  836.          (LPSTR)&IfdEntries)) {
  837.             DBMSG(("GtTiffInfo: can't read # of dir entries\n"));
  838.             goto cu0;
  839.         }
  840.  
  841.         /* loop through the entries
  842.          */
  843.         EntryOffset = th.thIfdOffset + sizeof(IfdEntries);
  844.         for (ii = 0; ii < IfdEntries; ii++, EntryOffset += sizeof(de)) {
  845.  
  846.             /* read the entry
  847.              */
  848.             if (err = GtTiffEntry (pDloc, th.thByteOrder, EntryOffset, &de)) {
  849.                 DBMSG(("GtTiffInfo: can't read entry.\n"));
  850.                 err = SUCCESS;
  851.                 continue;
  852.             }
  853.  
  854.             /* convert to a TFIELD structure, reading big fields as necessary
  855.              */
  856.             if (err = FillTField (pDloc, th.thByteOrder, &de, EntryOffset, &tf)) {
  857.                 DBMSG(("GtTiffInfo: FillTField\n"));
  858.                 err = SUCCESS;
  859.                 continue;
  860.             }
  861.  
  862.             /* check for bad values, convert from one format to another
  863.              * if necessary, and store the information in the appropriate
  864.              * TFIELD structure in the IMAG structure
  865.              */
  866.             if (err = NicefyTField (&tf, x)) {
  867.                 DBMSG(("GtTiffInfo: NicefyTField\n"));
  868.                 err = SUCCESS;
  869.                 continue;
  870.             }
  871.  
  872.         } /* end of direntry loop */
  873.         
  874.         /* check the offset of the next IFD
  875.          */
  876.         {
  877.             DWORD    NextIFD;
  878.             WORD    Dummy;
  879.             
  880.             if (err = GtData (pDloc, th.thByteOrder, EntryOffset, 1, TIFFLONG,
  881.              (LPSTR)&NextIFD)) {
  882.                 DBMSG(("GtTiffInfo: can't read next-IFD-offset\n"));
  883.                 err = IM_BAD_NEXT_IFD;
  884.                 goto cu0;
  885.             }
  886.             if (err = GtData (pDloc, th.thByteOrder, NextIFD, 1, TIFFSHORT,
  887.              (LPSTR)&Dummy)) {
  888.                 DBMSG(("GtTiffInfo: can't read next IFD\n"));
  889.                 err = IM_BAD_NEXT_IFD;
  890.                 goto cu0;
  891.             }
  892.         }
  893.  
  894.         /* miscellaneous correctness checks
  895.          */
  896.         if (err = CheckTiff (x)) {
  897.             /* DBMSG((" CheckTiff\n")); */
  898.             goto cu0;
  899.         }
  900.         
  901.         /* return
  902.          */
  903. cu0:    return err;
  904. }